using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.Outlook;
using Office.Utility.Extensions;

namespace Office.Utility.Toolbar
{
    public sealed class CommandBarManager
	{
        static ISynchronizeInvoke _invokeSync;

        readonly Explorers _explorers;
        readonly List<CommandBar> _commandBars = new List<CommandBar>();

		public CommandBarManager(_Application app)
		{
			_explorers = app.Explorers;
			_explorers.NewExplorer += OnNewExplorer;

		    if (_invokeSync != null) return;
		    var c = new Control();
		    c.CreateControl();
		    _invokeSync = c;
		}

        public void Shutdown()
        {
            _explorers.NewExplorer -= OnNewExplorer;

            foreach (var explorer in _explorers.ComLinq<Explorer>())
            {
                foreach (var t in _commandBars)
                    t.Detach(new WindowAdapter(explorer));
            }
        }

		void OnNewExplorer(Explorer explorer)
		{
            foreach (var t in _commandBars)
				t.Attach(explorer);
		}

		public void RegisterCommandBar(CommandBar commandbar)
		{
            _commandBars.Add(commandbar);

			foreach (Explorer explorer in _explorers)
                commandbar.Attach(explorer);
		}

        public void SetVisible(Toolbar toolbar, bool visible)
        {
            foreach (var bar in from explorer in _explorers.ComLinq<Explorer>()
                                from bar in explorer.CommandBars.ComLinq<Microsoft.Office.Core.CommandBar>()
                                where bar.Name == toolbar.Name
                                select bar)
            {
                bar.Visible = visible;
            }
        }

        public void SetVisible(Toolbar toolbar, ToolbarControl control, bool visible)
        {
            foreach (var barControl in from explorer in _explorers.ComLinq<Explorer>()
                                       from bar in explorer.CommandBars.ComLinq<Microsoft.Office.Core.CommandBar>()
                                       where bar.Name == toolbar.Name
                                       from barControl in bar.Controls.ComLinq<CommandBarControl>()
                                       where barControl.Parameter == control.Id
                                       select barControl)
            {
                barControl.Visible = visible;
            }
        }

        public void SetEnabled(Toolbar toolbar, ToolbarControl control, bool enabled)
        {
            foreach (var barControl in from explorer in _explorers.ComLinq<Explorer>()
                                       from bar in explorer.CommandBars.ComLinq<Microsoft.Office.Core.CommandBar>()
                                       where bar.Name == toolbar.Name
                                       from barControl in bar.Controls.ComLinq<CommandBarControl>()
                                       where barControl.Parameter == control.Id
                                       select barControl)
            {
                barControl.Enabled = enabled;
                return;
            }
        }

        //When using WordMail, the events fired by toolbar and menu items arrive on a background thread
        //CommandBarManager uses a ISynchronizeInvoke object (a control, set in the constructor) 
        //to dynamically invoke any toolbar or menu events on the correct thread
        internal static void DynamicInvoke(Delegate del, params object[] delParams)
        {
            if (_invokeSync == null)
                throw new NullReferenceException("You must create an instance of the CommandBarManager before calling the static DyanmicInvoke method");

            if (_invokeSync.InvokeRequired)
            {
                _invokeSync.Invoke(del, delParams);
            }
            else
            {
                del.DynamicInvoke(delParams);
            }
        }

	}
}
